package org.lysh.controller;

import lombok.extern.slf4j.Slf4j;
import org.lysh.enums.BusinessCode;
import org.lysh.exception.BusinessException;
import org.lysh.response.BlogResponse;
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpMediaTypeException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.multipart.support.MissingServletRequestPartException;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import java.util.Optional;

/**
 * @author liyishan
 * @date 2024/4/24 15:26
 * @apiNote
 */
@Slf4j
public class BaseController {

    @ExceptionHandler(Exception.class)
    @ResponseBody
    BlogResponse<?> exceptionHandler(Exception e) {
        log.error("SystemException[系统异常]", e);
        return new BlogResponse<>(BusinessCode.FATAL);
    }

    @ExceptionHandler(BusinessException.class)
    @ResponseBody
    BlogResponse<?> exceptionHandler(BusinessException e) {
        log.error("BusinessException[业务异常] code:-{}- msg:-{}-", e.getCode(), e.getMsg(), e);
        return new BlogResponse<>(e.getCode(), e.getMsg());
    }

    @ExceptionHandler(BindException.class)
    @ResponseBody
    BlogResponse<?> exceptionHandler(BindException e) {
        log.error("BindException[绑定异常]", e);
        return new BlogResponse<>(BusinessCode.ERROR_PARAMS.getCode(), e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
    }

    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseBody
    BlogResponse<?> exceptionHandler(IllegalArgumentException e) {
        log.error("IllegalArgumentException[校验错误]", e);
        return new BlogResponse<>(BusinessCode.ERROR_PARAMS.getCode(), e.getMessage());
    }

    @ExceptionHandler(HttpMediaTypeException.class)
    @ResponseBody
    BlogResponse<?> exceptionHandler(HttpMediaTypeException e) {
        log.error("HttpMediaTypeException[请求MediaType错误]", e);
        return new BlogResponse<>(BusinessCode.ERROR_PARAMS.getCode(), "请求方式错误");
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    BlogResponse<?> exceptionHandler(MethodArgumentNotValidException e) {
        log.error("MethodArgumentNotValidException[校验错误]", e);
        return new BlogResponse<>(BusinessCode.ERROR_PARAMS.getCode(), e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
    }

    @ExceptionHandler(HttpMessageConversionException.class)
    @ResponseBody
    BlogResponse<?> exceptionHandler(HttpMessageConversionException e) {
        log.error("HttpMessageConversionException[参数类型转换错误]", e);
        return new BlogResponse<>(BusinessCode.ERROR_PARAMS.getCode(), "参数格式错误");
    }

    @ExceptionHandler(MissingServletRequestPartException.class)
    @ResponseBody
    BlogResponse<?> exceptionHandler(MissingServletRequestPartException e) {
        log.error("MissingServletRequestPartException[缺少参数]", e);
        return new BlogResponse<>(BusinessCode.ERROR_PARAMS.getCode(), "请求参数 " + e.getRequestPartName() + " 不能为空");
    }

    @ExceptionHandler(MissingServletRequestParameterException.class)
    @ResponseBody
    BlogResponse<?> exceptionHandler(MissingServletRequestParameterException e) {
        log.error("MissingServletRequestParameterException[缺少参数]", e);
        return new BlogResponse<>(BusinessCode.ERROR_PARAMS.getCode(), "请求参数 " + e.getParameterName() + " 不能为空");
    }

    @ExceptionHandler(MissingPathVariableException.class)
    @ResponseBody
    BlogResponse<?> exceptionHandler(MissingPathVariableException e) {
        log.error("MissingPathVariableException[缺少路径参数]", e);
        return new BlogResponse<>(BusinessCode.ERROR_PARAMS.getCode(), "请求参数 " + e.getVariableName() + " 不能为空");
    }

    @ExceptionHandler(HttpMessageNotReadableException.class)
    @ResponseBody
    BlogResponse<?> exceptionHandler(HttpMessageNotReadableException e) {
        log.error("HttpMessageNotReadableException[请求体序列化失败]", e);
        return new BlogResponse<>(BusinessCode.ERROR_PARAMS.getCode(), "请求体格式错误");
    }

    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    @ResponseBody
    BlogResponse<?> exceptionHandler(MethodArgumentTypeMismatchException e) {
        log.error("MethodArgumentTypeMismatchException[请求参数类型错误]", e);
        return new BlogResponse<>(BusinessCode.ERROR_PARAMS.getCode(), "请求参数类型错误");
    }

    @ExceptionHandler
    @ResponseBody
    BlogResponse<?> exceptionHandler(ValidationException e) {
        log.error("ValidationException[校验错误]", e);
        String message = "校验错误";
        if (e instanceof ConstraintViolationException) {
            ConstraintViolationException exs = (ConstraintViolationException) e;
            Optional<ConstraintViolation<?>> optional = exs.getConstraintViolations().stream().findAny();
            message = optional.isPresent() ? optional.get().getMessage() : message;
        }
        return new BlogResponse<>(BusinessCode.ERROR_PARAMS.getCode(), message);
    }
}
